import DataExtraction.BSAIndexEntry

class BSAIndex:
    BSA_INDEX_SIZE = 18
    
    def __init__(self, entry_count = 0, global_bsa_data = None, global_bsa_size = 0):
        self._entry_count = entry_count
        self._global_bsa_data = global_bsa_data
        self._offset = 0
        self._entries_dict = {}
        self._file_size = global_bsa_size
        
        # iter stuff
        self._sorted_keys_iter = None    
        
    def __repr__(self):
        return "BSAIndex: [entry_count=" + str(self._entry_count) + "|file_size=" +\
            str(self._file_size) + "|offset=" + str(self._offset) + "|entries=" +\
            str(self._entries_dict) + "]"
    
    def __iter__(self):
        return self._entries_dict.__iter__()
    
    def __getitem__(self, item):
        return self._entries_dict.__getitem__(item)
    
    def iteritems(self):
        return self._entries_dict.iteritems()
    
    def iterkeys(self):
        return self._entries_dict.iterkeys()
    
    def itervalues(self):
        return self._entries_dict.itervalues()
    
    def items(self):
        return self._entries_dict.items()
    
    # getters
    def get_global_bsa_data(self):
        return self._global_bsa_data
    
    def get_entry_count(self):
        return self._entry_count
    
    def get_file_size(self):
        return self._file_size
    
    def get_entry(self, name):
        return self._entries_dict[name.upper()]

    def get_voc_entries(self):
        ret = []
        
        for entry in self._entries_dict.iterkeys():
            upper_entry = entry.upper()
            
            if upper_entry.rfind('.VOC') > 0:
                ret.append(self._entries_dict[upper_entry])
        
        return ret
    
    def get_cfa_entries(self):
        ret = []
        
        for entry in self._entries_dict.iterkeys():
            upper_entry = entry.upper()
            
            if upper_entry.rfind('.CFA') > 0:
                ret.append(self._entries_dict[upper_entry])
    
        return ret
    
    def get_dfa_entries(self):
        ret = []
        
        for entry in self._entries_dict.iterkeys():
            upper_entry = entry.upper()
            
            if upper_entry.rfind('.DFA') > 0:
                ret.append(self._entries_dict[upper_entry])
    
        return ret
    
    def get_cif_entries(self):
        ret = []
        
        for entry in self._entries_dict.iterkeys():
            upper_entry = entry.upper()
            
            if upper_entry.rfind('.CIF') > 0:
                ret.append(self._entries_dict[upper_entry])
    
        return ret
    
    # setters
    def set_global_bsa_data(self, global_bsa_data):
        self._global_bsa_data = global_bsa_data
        
    def set_entry_count(self, entry_count):
        self._entry_count = entry_count
        
    def set_file_size(self, file_size):
        self._file_size = file_size
        
    def load(self):
#===============================================================================
#        Accumulate the starting offset of each file/chunk in the BSA.  Start
#        off with this set to 2, since we need to skip the 2-byte word at the
#        beginning of the file that contains the size of the index table.
#===============================================================================
        local_offset = 2
        
        index_size = self._entry_count * self.BSA_INDEX_SIZE

        file_offset = self._file_size - index_size

        self._global_bsa_data.seek(file_offset)
#===============================================================================
#        Scan through the indices in order.  This is also the order in which
#        they are stored in the BSA file, which allows us to determine the
#        offset of the corresponding file/chunk in the BSA.  The index in
#        Global.BSA does not store offsets, only the size of the data.  Since
#        all data is packed without any padding, we need to accumulate the
#        sizes to figure out the offset of each file within Global.BSA. 
#===============================================================================
        for i in xrange(self._entry_count):
            index_entry = DataExtraction.BSAIndexEntry.BSAIndexEntry()
            index_entry.set_offset(local_offset)
            index_entry.read(self._global_bsa_data)

            local_offset += index_entry.get_size()
            
            # we in python have dictionaries, so we don't resort the array like winarena
            # it's also bloody faster than binary search
            self._entries_dict[index_entry.get_name()] = index_entry
        
        sorted_keys = self._entries_dict.keys()
        sorted_keys.sort()
        self._sorted_keys_iter = sorted_keys.__iter__()
